package com.foohoo.benchmark.collection;

import lombok.extern.slf4j.Slf4j;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 测试底层为数组方式实现的集合类(ArrayList)不指定大小对性能的影响
 * Benchmark                                Mode  Cnt      Score       Error  Units
 * ArrayListInitialSize.withInitialSize     avgt    3   8000.854 ±   573.810  ns/op
 * ArrayListInitialSize.withoutInitialSize  avgt    3  10211.176 ± 12853.520  ns/op
 * 一句话结论: 合理指定了初始大小的ArrayList扩容次数更少，可以节省扩容时旧数组复制到新数组的时间
 * 注: LinkedList同理
 *
 * @author mzdbxqh
 * @date 2020-10-28 21:42
 **/
@Slf4j
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 3, time = 1)
@Fork(1)
@Threads(1)
@State(Scope.Benchmark)
public class ArrayListInitialSize {

	private static final int LOOP_SIZE = 1024;

	private List<String> sourceList;

	@Setup
	public void initialize() {
		sourceList = new ArrayList<>(LOOP_SIZE);
		for (int i = 0; i < LOOP_SIZE; i++) {
			sourceList.add(Integer.toString(i));
		}
	}

	@Benchmark
	public void withInitialSize(Blackhole bh) {
		ArrayList<String> list = new ArrayList<>(LOOP_SIZE);
		for (String i : sourceList) {
			list.add(i);
		}
		bh.consume(list);
	}

	@Benchmark
	public void withoutInitialSize(Blackhole bh) {
		ArrayList<String> list = new ArrayList<>();
		for (String i : sourceList) {
			list.add(i);
		}
		bh.consume(list);
	}
}
